/**system core utils for safty utils,such as user login/ alter password/ update account info
 * fuzhou huilin corp.ltd @author lms 2016.07.14
 */
package com.fzrskj.cloud.free.sys.utils;

import com.fzrskj.cloud.free.consts.AppCode;
import com.fzrskj.cloud.free.consts.CConsts;
import com.fzrskj.cloud.free.core.tool.CEncryptTool;
import com.fzrskj.cloud.free.core.tool.CJsonTool;
import com.fzrskj.cloud.free.core.utils.CloudContextUtils;
import com.fzrskj.cloud.free.sys.dao.CFuncDao;
import com.fzrskj.cloud.free.sys.dao.CLogDao;
import com.fzrskj.cloud.free.sys.dao.CRoleDao;
import com.fzrskj.cloud.free.sys.bean.Role;
import com.fzrskj.cloud.free.sys.bean.User;
import com.fzrskj.cloud.free.sys.bean.Func;
import com.fzrskj.cloud.free.sys.bean.RuntimeLog;
import com.fzrskj.cloud.free.sys.dao.CUserDao;
import com.fzrskj.cloud.free.user.utils.UserAccountUtils;
import ms.core.consts.SysErr;
import ms.core.object.CObject;
import ms.core.tool.StrTool;
import net.sf.json.JSONArray;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class CUserUtils extends CObject{

	/**verify user login
	 * @param account user account
	 * @param pass user password
	 * @return null for failure or User object
	 * by fuzhou huilin corp.ltd @author lms 2016.08.18
	 */
	public User userLogin(String account, String pass, String visitIp){
		CUserDao obj = new CUserDao();
		User u = obj.queryUser(account);
		String code = obj.getErrCode();
		if (!code.equals(SysErr.CODE_SUCCESS)){
			obj.dispose();
			this.setErrCode(code);
			return null;
		}

		if (u==null){
			obj.dispose();
			this.setErrCode(SysErr.USER_NOT_EXISTS);
			return null;
		}

		if (CloudContextUtils.getAgentId() > 0) {
			if (!u.getPassword().equals(UserAccountUtils.encodePassword(pass))) {
				obj.dispose();
				this.setErrCode(SysErr.USER_PASSWORD_ERR);
				return null;
			}
		} else {
			if (!u.getPassword().equals(CEncryptTool.encodePassword(pass))) {
				obj.dispose();
				this.setErrCode(SysErr.USER_PASSWORD_ERR);
				return null;
			}
		}
		u.setFuncs(obj.queryUserFuncs(u.getRoles()));
		u.setVisitIp(visitIp);
		u.setVisitTime(new Date());
		obj.updateVisit(u.getId(), visitIp);
		obj.dispose();
		return u;
	}

	private JSONArray getUserRightFuns(JSONArray aryMenu, JSONArray aryUser){
		
		if ((aryUser==null) || (aryUser.size()==0)) {
			return null;
		}

		JSONArray rets = new JSONArray();
		for(int i=0; i<aryUser.size(); i++){
			String funId = (String) CJsonTool.getJsonArrayValue(aryUser, i, "id");
			for(int j=0; j<aryMenu.size(); j++){
				String menuId = (String) CJsonTool.getJsonArrayValue(aryMenu, j, "id");
				if (funId.toLowerCase().equals(menuId.toLowerCase())){
					rets.add(aryMenu.get(j));
				}
			}
		}
		return rets;
	}
	
	
	private boolean isValidMenu(Func func, List<Func> funcs, int index){
		if (!StrTool.isBlankStr(func.getFuncs())) {
			return true;
		}

		boolean ret = false;
		for (int i=index; i<funcs.size(); i++){
			Func tmp = funcs.get(i);
			if (tmp.getFunId().startsWith(func.getFunId()) && !StrTool.isBlankStr(tmp.getFuncs())){
				ret = true;
				break;
			}
		}
		return ret;
	}

	/**
	 * to get user's function menu
	 * @param userFuns
	 * @return
	 */
	public List<Func> queryUserFunc(String userFuns){
		JSONArray aryFuns = CJsonTool.getJsonArray(userFuns);
		if ((aryFuns==null) || (aryFuns.size()<=0)) 
		{
			this.setErrCode(SysErr.CODE_SUCCESS);
			return null;
		}

		CFuncDao dao = new CFuncDao();
		List<Func> funs = dao.queryFunc();
		String err = dao.getErrCode();
		this.setErrCode(err);
		dao.dispose();
		if (!err.equals(SysErr.CODE_SUCCESS)) {
			return null;
		}
		
		//to filter user's menu
		List<Func> filters = new ArrayList<Func>();
		for(int i=0; i<funs.size(); i++){
			Func fun = funs.get(i);
			if (StrTool.isBlankStr(fun.getFuncs())){
				filters.add(fun);
				continue;	//parent menu
			}

			JSONArray aryMenu = CJsonTool.getJsonArray(fun.getFuncs());
			JSONArray tmp = getUserRightFuns(aryMenu, aryFuns);
			if (tmp==null || tmp.size()<=0) {
				continue;
			}

			fun.setFuncs(tmp.toString());
			filters.add(fun);
		}
		//to filter invalid menu
		List<Func> rets = new ArrayList<Func>();
		for (int j=0; j<filters.size(); j++){
			if (isValidMenu(filters.get(j),filters, j+1)) {
				rets.add(filters.get(j));
			}
		}
		return rets;
	}
	
	/**to add admin account
	 * @param user User bean object
	 * @return -1 system error; 0 user exists; >0 new user id
	 */
	public int addUser(User user){
		if ((user==null) || StrTool.isBlankStr(user.getAccount())){
			return -1;
		}

		CUserDao obj = new CUserDao();
		int ret = obj.newUser(user);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}
	
	/**to delete admin account
	 * @param rid user record id
	 * @return >=0 success; <0 means system error
	 */
	public int delUser(int rid){
		CUserDao obj = new CUserDao();
		User u = obj.queryUser(rid);
		String err = obj.getErrCode();
		if (!err.equals(SysErr.CODE_SUCCESS)){
			this.setErrCode(obj.getErrCode());
			obj.dispose();
			return -1;
		}
		if (u==null){
			this.setErrCode(SysErr.USER_NOT_EXISTS);
			obj.dispose();
			return 0;
		}
		if (u.getAccount().toLowerCase().equals("admin")){
			this.setErrCode(AppCode.SYS_ACCOUNT);
			obj.dispose();
			return 0;
		}
		int ret = obj.delUser(rid);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}

	/**
	 * to modify admin account
	 * @param user
	 * @return {"code":"failure/success","tips":"runtime info"}
	 */
	public int modUser(User user){
		CUserDao obj = new CUserDao();
		int ret = obj.modUser(user);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}

	/**
	 * to set admin role
	 * @param account
	 * @param roles
	 * @return <=0 failure;>0 success
	 */
	public int setUserRole(String account, String roles){
		String jsonRole = "[";
		List<String> tmp = StrTool.spilitString(roles, ",");
		for(int i=0; i<tmp.size(); i++){
			jsonRole = jsonRole+String.format("{\"id\":\"%s\"}",tmp.get(i));
			if (i<tmp.size()-1) {
				jsonRole =jsonRole+",";
			}
		}
		jsonRole = jsonRole+"]";
		CUserDao obj = new CUserDao();
		int ret = obj.setUserRole(account,jsonRole);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}
	
	/**to modify user's password
	 * @param rid user record id
	 * @param oldpass old password
	 * @param newpass new password
	 * @return <=0 failure; >0 success
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public int setUserPassword(int rid, String oldpass, String newpass){
		//user exists
		CUserDao obj = new CUserDao();
		User user = obj.queryUser(rid);
		String code = obj.getErrCode();
		if (!code.equals(SysErr.CODE_SUCCESS)){
			this.setErrCode(obj.getErrCode());
			obj.dispose();
			return -1;
		}
		
		if (user==null){
			obj.dispose();
			this.setErrCode(SysErr.USER_NOT_EXISTS);
			return 0;	
		}
		
		//old password is right?
		oldpass = CEncryptTool.encodePassword(oldpass);
		if (!oldpass.equals(user.getPassword())){
			obj.dispose();
			this.setErrCode(SysErr.USER_OLD_PASSWORD_ERR);
			return 0;
		}

		//set new password
		newpass = CEncryptTool.encodePassword(newpass);
		int ret = obj.setUserPassword(rid, newpass);
		setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}
	
	/**to modify user's status
	 * @param rid user record id
	 * @param state state 0-正常; 1-停用; 2-冻结
	 * @return <=0 failure; >0 success
	 * @author by fuzhou huilin corp.ltd 816 2016.10.12
	 */
	public int setUserStatus(int rid, int state){
		//user exists
		CUserDao obj = new CUserDao();
		User user = obj.queryUser(rid);
		String code = obj.getErrCode();
		if (!code.equals(SysErr.CODE_SUCCESS)){
			setErrCode(obj.getErrCode());
			obj.dispose();
			return -1;
		}
		if (user==null){
			obj.dispose();
			setErrCode(SysErr.USER_NOT_EXISTS);
			return 0;
		}
		//set new state
		int ret = obj.setUserStatus(rid, state);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}

	//to query user total rows
	public int queryUser(String account){
		CUserDao obj = new CUserDao();
		int rows = obj.queryUserNum();
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return rows;
	}
	/**to query user info
	 * @param page current page, start from 1
	 * @param pagesize size of page
	 * @param account user name
	 * @return null if system error/over page; User List when success
	 */
	public List<User> queryUser(int page, int pagesize, String account){
		if (page<=0) {
			page = 1;
		}
		if (pagesize<=0) {
			pagesize = CConsts.PAGE_SIZE;
		}

		int rows = queryUser(account);
		int pages= Math.round((rows+pagesize-1)/pagesize);
		if (page>pages){
			this.setErrCode(SysErr.SYS_DATA_NOT_FOUND);
			return null;
		}

		CUserDao obj = new CUserDao();
		List<User> users = obj.queryUserList(page, pagesize);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return users;
	}

	/**to add role
	 * @param roleName role name
	 * @param roleCName Chinese name
	 * @param remark remark of role
	 * @return <=0 failure, success for new role id
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public int newRole(String roleName, String roleCName, String remark){
		CRoleDao obj = new CRoleDao();
		Role tmp = obj.queryRole(roleName);
		if (tmp!=null){
			obj.dispose();
			this.setErrCode(SysErr.USER_ROLE_EXISTS);
			return 0;
		}

		Role role = new Role();
		role.setRoleName(roleName);
		role.setRoleCName(roleCName);
		role.setRemark(remark);

		int ret = obj.newRole(role);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}

	/**to update role information
	 * @param roleName
	 * @return <0 failure; >=0 success
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public int delRole(String roleName){
		if (roleName.toLowerCase().equals("admin")){
			this.setErrCode(AppCode.SYS_ROLE);
			return 0;
		}

		//remove user's role information
		CUserDao uObj = new CUserDao();
		uObj.delUsersRole(roleName);
		uObj.dispose();

		//delete role
		CRoleDao rObj = new CRoleDao();
		int ret = rObj.delRole(roleName);
		this.setErrCode(rObj.getErrCode());
		rObj.dispose();
		return ret;
	}

	/**to update role information
	 * @param rid role id
	 * @param roleCName role Chinese name
	 * @param remark role remark
	 * @return <0 means failure; >=0 success
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public int modRole(int rid, String roleCName, String remark){
		CRoleDao obj = new CRoleDao();
		int ret = obj.modRole(rid,roleCName,remark);
		this.setErrCode(obj.getErrCode());
		obj.dispose();
		return ret;
	}

	/**to set role function
	 * @param rid role id
	 * @param funs role functions
	 * @return <0 failure; >=0 success
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public int setRoleFun(int rid, String funs){
		String jsonFun = "[";
		List<String> tmp = StrTool.spilitString(funs, ",");
		for(int i=0; i<tmp.size(); i++){
			jsonFun = jsonFun+String.format("{\"id\":\"%s\"}",tmp.get(i));
			if (i<tmp.size()-1) {
				jsonFun =jsonFun+",";
			}
		}
		jsonFun = jsonFun+"]";

		CRoleDao obj = new CRoleDao();
		int ret = obj.setRoleFun(rid, jsonFun);
		this.setErrCode(obj.getErrCode(), obj.getMsg());
		obj.dispose();
		return ret;
	}

	/**to query role
	 * @return failure return null; other reutrn Role list
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public List<Role> queryRole(int roleId){
		CRoleDao obj = new CRoleDao();
		List<Role> rs = obj.queryRole(roleId);
		this.setErrCode(obj.getErrCode(), obj.getMsg());
		obj.dispose();
		return rs;
	}

	/**to query system functions
	 * @return failure return null; other reutrn Func list
	 * @author by fuzhou huilin corp.ltd lms 2016.08.18
	 */
	public List<Func> queryFuns(){
		CFuncDao obj = new CFuncDao();
		List<Func> funs = obj.queryFunc();
		this.setErrCode(obj.getErrCode(), obj.getMsg());
		obj.dispose();
		return funs;
	}

	//to query log record count
	public int queryRuntimeLog(long fromtime, long totime){
		CLogDao obj = new CLogDao();
		int rows = obj.queryRuntimeLog(fromtime, totime);
		obj.dispose();
		return rows;
	}

	/**to query runtime log
	 * @param page page index, start from 1
	 * @param pagesize HttpServletResponse of current user
	 * @param fromtime function parameter, format: p={"fromTime":yyyyMMddhhmmss,"toTime":yyyyMMddhhmmss,"page",n,"pageSize":m}
	 * @param totime session id of current user
	 * @author by fuzhou huilin corp.ltd lms 2016.08.03
	 */
	public List<RuntimeLog> queryRuntimeLog(int page, int pagesize, long fromtime, long totime){
		if (page<1) {
			page = 1;
		}
		if (pagesize<1) {
			pagesize = CConsts.PAGE_SIZE;
		}
		CLogDao obj = new CLogDao();
		List<RuntimeLog> logs = obj.queryRuntimeLog(fromtime, totime, page, pagesize);
		this.setErrCode(obj.getErrCode(), obj.getMsg());
		obj.dispose();
		return logs;
	}

	/**
	 * 查询操作日志详情
	 * @param id
	 * @return
	 */
	public RuntimeLog queryRLDetail(long id){
		CLogDao dao = new CLogDao();
		RuntimeLog logDetail = dao.queryRuntimeLogDetail(id);
		String code = dao.getErrCode();
		this.setErrCode(code);
		dao.dispose();
		return logDetail;
	}

	/**
	 * 查询后台账号密码是否存在
	 * @param userName
	 * @param oldPassword
	 * @return
	 */
	public User queryPassword(String userName,String oldPassword){
		CUserDao dao = new CUserDao();
		String adminPass = CEncryptTool.md5Encode(oldPassword+"~omg~");
		if (CloudContextUtils.getAgentId() > 0) {
			adminPass = UserAccountUtils.encodePassword(oldPassword);
		}
		User user = dao.queryPassword(userName, adminPass);
		String code = dao.getErrCode();
		this.setErrCode(code);
		dao.dispose();
		return user;
	}

	/**
	 * 根据用户名修改密码
	 * @param userName
	 * @param newPassword
	 * @return
	 */
	public int uptadminpas(String userName,String newPassword){
		CUserDao dao = new CUserDao();
		String adminPass = CEncryptTool.md5Encode(newPassword+"~omg~");
		if (CloudContextUtils.getAgentId() > 0) {
			adminPass = UserAccountUtils.encodePassword(newPassword);
		}
		int ret = dao.uptadminpas(userName, adminPass);
		String code = dao.getErrCode();
		this.setErrCode(code);
		dao.dispose();
		return ret;
	}

	/**
	 * 获取角色
	 * @param roleName
	 * @return
	 */
	public Role getRole(String roleName){
		CRoleDao dao = new CRoleDao();
		Role role = dao.queryRole(roleName);
		String code = dao.getErrCode();
		this.setErrCode(code);
		dao.dispose();
		return role;
	}

	/**
	 * 获取自动分客服或技术.
	 * @param groupCode 2或3.
	 * @return sys user
	 */
	public static User getAllotUser(Integer groupCode) {
		CUserDao userDao = new CUserDao();
		User user = userDao.getAllotUser(groupCode);
		userDao.dispose();
		return user;
	}

	/**
	 * 通过账号ID获取用户.
	 * @param accountId 账号ID.
	 * @return user info.
	 */
	public static User getUser(Integer accountId) {
		CUserDao userDao = new CUserDao();
		User user = userDao.getUser(accountId);
		userDao.dispose();
		return user;
	}

	/**
	 * 无代理隔离查询.
	 * @param cdt 查询条件.
	 * @return 查询结果.
	 */
	public List<User> queryUserNoAgent(Map<String, Object> cdt) {
		CUserDao userDao = new CUserDao();
		List<User> userList = userDao.queryUserNoAgent(cdt);
		userDao.dispose();
		return userList;
	}

	public Integer modifyUserNotAgent(Map<String, Object> values, Map<String, Object> cdt) {
		CUserDao userDao = new CUserDao();
		Integer affect = userDao.modifyUserNotAgent(values, cdt);
		userDao.dispose();
		return affect;
	}

	public Integer newUserNotAgent(User user) {
		CUserDao userDao = new CUserDao();
		Integer affect = userDao.newUserNotAgent(user);
		userDao.dispose();
		return affect;
	}

	public Integer copyAdminRight(Integer agentId) {
		CUserDao userDao = new CUserDao();
		Integer affect = userDao.copyAdminRight(agentId);
		userDao.dispose();
		return affect;
	}

	public List<User> qryCrmUserList(){
		CUserDao userDao = new CUserDao();
		List<User> userList = userDao.qryCrmUserList();
		userDao.dispose();
		return userList;
	}

	public static void main(String[] args){
		CUserUtils userUtils = new CUserUtils();
		List<User> list = userUtils.qryCrmUserList();
	}
}